#include <sstream>
#include <iostream>
#include <string>
#include <ext/hash_map>
#include <map>
#include <time.h>
#include <stdlib.h>

using namespace std;

#include "lock.hpp"
#include "condition.hpp"
#include "common.hpp"
#include "thread.hpp"
#include "log.hpp"
#include "queue.hpp"
#include "fixed_size_allocator.hpp"

using namespace thread;


ThreadPool<std::string, std::string, Queue, iThreadMultipleQueue> consumer_pool("ConsumerThreadPool");

struct Hash
{
	int operator () (const std::string & str, int size) const
	{
		size_t value = __gnu_cxx::__stl_hash_string(str.c_str());
		return (value % size);
	}
};

class ConsumerThread: public Thread
{
	protected :
		virtual void run()
		{
			std::ostringstream oss;
			while (true)
			{
				std::string request;
				consumer_pool.get_request(index(), request);

				oss << request << " consumer pid: " << id() << " consume";
				
				consumer_pool.put_response(oss.str());
				oss.str("");
			}
		}
	public :

};

class ProducerThread: public Thread
{
	protected :
		virtual void run()
		{
			std::ostringstream oss;
			int index = 0;

			Hash hash_func;

			while (true)
			{
				oss << "producer pid: " << id() << " product " << ++ index;

				consumer_pool.put_request(oss.str(), hash_func);

				oss.str("");
			}
		}
	public :

};
class OutputThread : public Thread
{
	protected : 
		virtual void run()
		{
			while (true)
			{
				std::string response;
				consumer_pool.get_response(response);

				std::cout << response << std::endl;
			}
		}
};

void test_thread_pool()
{
	const static int CONSUMER_SIZE = 4;
	const static int PRODUCER_SIZE = 2;

	for (int i = 0; i < CONSUMER_SIZE; ++ i)
	{
		consumer_pool.add_thread(new ConsumerThread);
	}

	for (int i = 0; i < PRODUCER_SIZE; ++ i)
	{
		consumer_pool.add_thread(new ProducerThread);
	}

	consumer_pool.add_thread(new OutputThread);

	consumer_pool.start();


	while (true)
	{
		sleep(100000);
	}
}


int main(int argc, char * argv[])
{
	test_thread_pool();

	return 0;
}

